#include "StepByStep.h"

void InsertActKnowledge(Bool After, ActKnowledge *ActK1, ActKnowledge *ActK2)
{
  PredKnowledge *Parent;
  ActKnowledge  *ActK;

  Parent = ActK1->Parent;

  if (After) ActK = ActK1->next;
  else {
         ActK = ActK1;
         ActK1 = ActK1->prev;
  }

  ActK2->next = ActK;
  ActK2->prev = ActK1;

  if (ActK1 == NULL) Parent->Act = ActK2;
  else ActK1->next = ActK2;

  if (ActK != NULL) ActK->prev = ActK2;

  Parent->NumAct++;
}

void DeleteActKnowledge(ActKnowledge *ActK)
{
  PredKnowledge *Parent;
  ActKnowledge  *ActK1, *ActK2;

  Parent = ActK->Parent;

  ActK1 = ActK->prev;
  ActK2 = ActK->next;
  if (ActK1 == NULL) Parent->Act = ActK2;
  else ActK1->next = ActK2;
  if (ActK2 != NULL) ActK2->prev = ActK1;

  FreeActKnowledge(ActK);
  Parent->NumAct--;
}

Bool PredObstructActionOfPred(PredKnowledge *Pd1, PredKnowledge *Pd2)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  Bool           Ok1, Ok2;

  if (Pd2 == NULL) return FALSE;

  Ok1 = FALSE;
  for (ActK = Pd2->Act; !Ok1 && ActK != NULL; ActK = ActK->next) {
    Ok2 = TRUE;
    for (PC = ActK->PC; Ok2 && PC != NULL; PC = PC->next)
      if (CheckDomainLawForPreds(Law0, ATOM, Pd1, NOT, PC))   // Pd1 --> (not PC)
         Ok2 = !CheckDomainLawForPreds(Law0, ATOM, PC, NOT, Pd1); // PC --> (not Pd1)

    Ok1 = Ok1 || Ok2;
  }

  return !Ok1;
}

Bool NOTPredInEffectOfAction(PredKnowledge *Pred, PENode *Effect)
{
  while (Effect != NULL) {
    if (Effect->Delete==Pred->SAT && NOTPredInOneEffect(Pred, Effect))
       break;

    Effect = Effect->next;
  }

  return (Effect != NULL);
}

// Pd1 obstructs one PC of Actions of Pd2
Bool ObstructNextLevelPred(PredKnowledge *Pd1, PredKnowledge *Pd2)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1;
  int            Step;

//PrintPredication(1, Pd1); fprintf(Output, "\n");
//PrintPredication(1, Pd2); fprintf(Output, "\n");
  for (ActK = Pd2->Act; ActK != NULL; ActK = ActK->next) {
    if (!IsValid(Pd2, ActK)) continue;

    for (PC = ActK->PC; PC != NULL; PC = PC->next) {
      for (ActK1 = Pd1->Act; ActK1 != NULL; ActK1 = ActK1->next)
        if (IsValid(Pd1, ActK1) && !NOTPredInEffectOfAction(PC, ActK1->Effect))
           break;

      if (ActK1 == NULL) {
         // Pd1 ==> (not PC), or Pd1 =/=> PC
         Step = CheckDomainLawForPreds(Law0, ATOM, Pd1, NOT, PC);
         if (Step == NOLAW) Step = CheckDomainLawForPreds(Law3, ATOM, Pd1, ATOM, PC);

         if (Step != NOLAW) break;
      }
    }

    if (PC == NULL) return FALSE;
  }

  return TRUE;
}

Bool IsCommonPC(ActKnowledge *ActK, PredKnowledge *PC)
{
  PredKnowledge *PC1;
  ActKnowledge  *ActK1;
  TypedList     *Pt1, *Pt2;
  int            i, Num;

  Num = NumParaOfPred(PC->PredNo);
  for (ActK1 = ActK->next; ActK1 != NULL; ActK1 = ActK1->next) {
    if (ActK1->UComplete) continue;

    for (PC1 = ActK1->PC; PC1 != NULL; PC1 = PC1->next) {
      if (PC->Type != PC1->Type || PC->PredNo != PC1->PredNo) continue;

      Pt1 = PC->Para;   Pt2 = PC1->Para;
      for (i = 0; i < Num; i++,Pt1++,Pt2++)
        if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) break;

      if (i == Num) break;
    }

    if (PC1 == NULL) break;
  }

  return (ActK1 == NULL);
}

// The Common PCs of Pd2 are deleted by common effect of Pd1
Bool PredObsPred(PredKnowledge *Pd1, PredKnowledge *Pd2)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  TypedList     *Pt1;
  TokenList     *Pt2;
  PENode        *PE;

//PrintPredication(1, Pd1); fprintf(Output, "\n");
//PrintPredication(1, Pd2); fprintf(Output, "\n");
  ActK = Pd2->Act;
  while (ActK->UComplete) ActK = ActK->next;

  for (PC = ActK->PC; PC != NULL; PC = PC->next) {
    if (!IsCommonPC(ActK, PC)) continue;

    for (PE = Pd1->CEffect; PE != NULL; PE = PE->next) {
      Pt2 = PE->Pred;
      if (PC->Type==PE->Type || PC->PredNo!=Pt2->VList.ParaIdx) continue;

      Pt1 = PC->Para;
      for (Pt2 = Pt2->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
        if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) break;

      if (Pt2 == NULL) break;
    }

    if (PE != NULL) return TRUE;
  }

  return FALSE;
}

void HandleTwoLeaves(ReadyTreeLeaf *PT1, ReadyTreeLeaf *PT2)
{
  PredKnowledge *Pd1, *Pd2, *PC;
  ActKnowledge  *ActK;

  Pd1 = PT1->Pred;
  if (Pd1->Level == 0) {
     PT2->Ready = FALSE;
     return;
  }

  Pd2 = PT2->Pred;   ActK = Pd2->PAct;
  if (ActK != NULL)
     for (PC = ActK->PC; PC != NULL; PC = PC->next)
       if (CheckDomainLawForPreds(Law0, ATOM, PC, NOT, Pd1)) {  // PC --> (not Pd1)
          PT1->Ready = FALSE;
          return;
       }

  if (PredObstructActionOfPred(Pd1, Pd2->Parent)) PT1->Ready = FALSE;
  else PT2->Ready = FALSE;
}

Bool HandleTwoPredsWithOtherPreds(ReadyTreeLeaf *PT1, ReadyTreeLeaf *PT2, PredKnowledge *Pd1, PredKnowledge *Pd2)
{
  int Obs1, Obs2;

  // Pd1 ==> (not Pd2), or Pd1 =/=> Pd2
  Obs1 = CheckDomainLawForPreds(Law0, ATOM, Pd1, NOT, Pd2);
  if (Obs1 == NOLAW) Obs1 = CheckDomainLawForPreds(Law3, ATOM, Pd1, ATOM, Pd2);

  // Pd2 ==> (not Pd1), or Pd2 =/=> Pd1
  Obs2 = CheckDomainLawForPreds(Law0, ATOM, Pd2, NOT, Pd1);
  if (Obs2 == NOLAW) Obs2 = CheckDomainLawForPreds(Law3, ATOM, Pd2, ATOM, Pd1);

  if (Obs1 == Obs2) return FALSE;

  if (Obs1 && (!Obs2 || Obs1<Obs2)) PT1->Ready = FALSE;
  else PT2->Ready = FALSE;

  return TRUE;
}

Bool HandleTwoParentLeaves(ReadyTreeLeaf *PT1, ReadyTreeLeaf *PT2)
{
  PredKnowledge *Pd1, *Pd2, *Pd3, *Pd4;
//Bool           B1, B2;

  Pd1 = PT1->Pred;   Pd2 = PT2->Pred;
  Pd3 = Pd1->Parent; Pd4 = Pd2->Parent;

  if (Pd3 == NULL && Pd4 == NULL) return FALSE;

  if (Pd3 == NULL) return HandleTwoPredsWithOtherPreds(PT1, PT2, Pd1, Pd4);

  if (Pd4 == NULL) return HandleTwoPredsWithOtherPreds(PT1, PT2, Pd3, Pd2);

  if (HandleTwoPredsWithOtherPreds(PT1, PT2, Pd3, Pd4)) return TRUE;

/*B1 = PredObsPred(Pd1, Pd2);  // The relation of two predications
  B2 = PredObsPred(Pd2, Pd1);
  if (B1 != B2) {
     if (B1) PT1->Ready = FALSE;
     else PT2->Ready = FALSE;
  }*/
  return FALSE;
}

Bool PredDeletePCOfPred(PredKnowledge *Pd1, PredKnowledge *Pd2)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  TypedList     *Pt1;
  TokenList     *Pt2;
  PENode        *PE;

//PrintPredication(1, Pd1); fprintf(Output, "\n");
//PrintPredication(1, Pd2); fprintf(Output, "\n");
  ActK = Pd2->Act;
  while (ActK->UComplete) ActK = ActK->next;

  for (PE = Pd1->CEffect; PE != NULL; PE = PE->next) {
    Pt2 = PE->Pred;
//PrintOnePred(1, PE); fprintf(Output, "\n");

    for (PC = ActK->PC; PC != NULL; PC = PC->next) {
      if (PC->Type==PE->Type || PC->PredNo!=Pt2->VList.ParaIdx ||
          !IsCommonPC(ActK, PC)) continue;

      Pt1 = PC->Para;
      for (Pt2 = Pt2->next; Pt2 != NULL; Pt2 = Pt2->next)
        if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) break;

      if (Pt2 == NULL) break;
    }

    // PC -> (not Pd1)
    if (PC!=NULL && CheckDomainLawForPreds(Law0, ATOM, PC, NOT, Pd1) != NOLAW)
       return TRUE;
  }

  return FALSE;
}

void HandleTwoLastLeaves(ReadyTreeLeaf *PT1, ReadyTreeLeaf *PT2)
{
  PredKnowledge *Pd1, *Pd2;
  Bool           B1, B2;

  Pd1 = PT1->Pred;  Pd2 = PT2->Pred;

//PrintPredication(1, Pd1); fprintf(Output, "\n");
//PrintPredication(1, Pd2); fprintf(Output, "\n");

  // Pd1 --> Pd2, Pd2 --> Pd1
  B1 = CheckDomainLawForPreds(Law0, ATOM, Pd1, ATOM, Pd2);
  B2 = CheckDomainLawForPreds(Law0, ATOM, Pd2, ATOM, Pd1);
  if (B1 != B2) {
     if (B1 && PT1->Ready) { HandleTwoLeaves(PT1, PT2);  return; }
     if (B2 && PT2->Ready) { HandleTwoLeaves(PT2, PT1);  return; }
  }

  if (HandleTwoPredsWithOtherPreds(PT1, PT2, Pd1, Pd2)) return;

  B1 = ObstructNextLevelPred(Pd1, Pd2);
  B2 = ObstructNextLevelPred(Pd2, Pd1);
  if (B1 != B2) {
     if (B1) PT1->Ready = FALSE;
     else PT2->Ready = FALSE;
     return;
  }

  // Pd1 =\=> Pd2, Pd2 =\=> Pd1
  B1 = CheckDomainLawForPreds(Law3, ATOM, Pd1, ATOM, Pd2);
  B2 = CheckDomainLawForPreds(Law3, ATOM, Pd2, ATOM, Pd1);
  if (B1 != B2) {
     if (B1 && (!B2 || B1<B2)) PT1->Ready = FALSE;
     else PT2->Ready = FALSE;

     return;
  }

  if (HandleTwoParentLeaves(PT1, PT2)) return;

  // The relation of two predications
  B1 = PredObsPred(Pd1, Pd2);
  B2 = PredObsPred(Pd2, Pd1);
  if (B1 != B2) {
     if (B1) PT1->Ready = FALSE;
     else PT2->Ready = FALSE;
  }

  if (!B1) return;

  B1 = PredDeletePCOfPred(Pd1, Pd2);
  B2 = PredDeletePCOfPred(Pd2, Pd1);
  if (B1 != B2) {
     if (B1) PT1->Ready = FALSE;
     else PT2->Ready = FALSE;
  }
}

void InsertOnePredOfPlanTree(OneTarget *OT, PredKnowledge *Pd)
{
  PlanTreeLeaf *PT;

  PT = (PlanTreeLeaf *) calloc(1, sizeof(PlanTreeLeaf));

  PT->Delete = FALSE;
  PT->Index = NOFOUND;
  PT->Pred = Pd;

  PT->next = OT->Leaf;
  OT->Leaf = PT;
}

void GetLeavesOfOneTarget(OneTarget *OT, PredKnowledge *Pd)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  Bool           Ok;

  if (!Pd->Fact && Pd->Act==NULL) {
     InsertOnePredOfPlanTree(OT, Pd);
     return;
  }

  for (ActK = Pd->Act; ActK != NULL; ActK = ActK->next)
    if (IsValid(Pd, ActK)) {
       Ok = TRUE;
       for (PC = ActK->PC; PC != NULL; PC = PC->next)
         if (PC->Act != NULL) {
            GetLeavesOfOneTarget(OT, PC);
            Ok = FALSE;
         }

       if (Ok) { InsertOnePredOfPlanTree(OT, Pd);  break; }
    }
}

ReadyTreeLeaf* GetReadyLeavesOfPlanTree(ReadyTreeLeaf *PT)
{
  ReadyTreeLeaf *PT1, *PT2, *PT3, *PT4, *PT5;

  if (PT == NULL) return NULL;  // Finished Predication

PrintPlanTreeLeaf("Begin", PT);
  for (PT1 = PT; PT1->next != NULL; PT1 = PT1->next) {
    if (IsClass(PT1->Pred->PredNo, ASCENDING)) continue;

    for (PT2 = PT1->next; PT2 != NULL; PT2 = PT2->next)
      if (!IsClass(PT2->Pred->PredNo, ASCENDING) &&
          (PT1->Ready || PT2->Ready) &&
          !EqualTwoPredications(PT1->Pred, PT2->Pred))
         HandleTwoLastLeaves(PT1, PT2);
  }

PrintPlanTreeLeaf("End", PT);
  PT3 = NULL;
  for (PT1 = PT; PT1 != NULL; PT1 = PT2) {
    PT2 = PT1->next;
    if (!PT1->Ready) {
       FreePredKnowledge(PT1->Pred);
       free(PT1);
    }
    else {
           if (PT3 == NULL) PT = PT1;
           else PT3->next = PT1;
           PT3 = PT1;
    }
  }
  PT3->next = NULL;

//PrintPlanTreeLeaf("End", PT);
  for (PT1 = PT; PT1 != NULL; PT1 = PT1->next) {
    PT2 = PT1;
    for (PT3 = PT1->next; PT3 != NULL; PT3 = PT4) {
      PT4 = PT3->next;
      if (!EqualTwoPredications(PT1->Pred, PT3->Pred))
         PT2 = PT3;
      else {
             FreePredKnowledge(PT3->Pred);
             free(PT3);
             PT2->next = PT4;
      }
    }
    PT2->next = NULL;
  }
//PrintPlanTreeLeaf("End", PT);

  // Sorting ready leaves of plan tree
  PT1 = PT->next;
  PT->next = NULL;  PT5 = PT;
  while (PT1 != NULL) {
    PT2 = PT1->next;

    PT4 = NULL;
    for (PT3 = PT; PT3 != NULL; PT4=PT3,PT3=PT3->next)
      if ( PT3->Pred->NumAct > PT1->Pred->NumAct) break;

    if (PT4 == NULL) { PT1->next = PT;  PT = PT1; }
    else {
           PT1->next = PT4->next;
           PT4->next = PT1;
           if (PT5 == PT4) PT5 = PT1;
    }

    PT1 = PT2;
  }
  PT5->next = NULL;

//PrintPlanTreeLeaf("End", PT);

  return PT;
}

void GetCommonEffectOfPred(PredKnowledge *Pd)
{
  ActKnowledge *ActK, *ActK1;
  TokenList    *Pt;
  PENode       *PE1, *PE2, *PE3, *PE4, *PE5;
  int          i, j, *EffIdx;

  EffIdx = (int *) calloc(Pd->NumAct, sizeof(int));

  ActK = Pd->Act;
  PE3 = NULL;
  for (PE1 = ActK->Effect; PE1 != NULL; PE1 = PE4) {
    PE4 = PE1->next;

    for (Pt = PE1->Pred->next; Pt != NULL; Pt = Pt->next)
      if (Pt->VList.NumValue != 1) break;

    if (Pt != NULL) { PE3 = PE1;  continue; }

    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      for (j=0,PE2=ActK1->Effect; PE2 != NULL; j++,PE2=PE2->next)
        if (PE2->Type==PE1->Type && EqualTwoTokenLists(PE1->Pred, PE2->Pred)) {
           EffIdx[i] = j;
           break;
        }

      if (PE2 == NULL) break;
    }

    if (ActK1 != NULL) { PE3 = PE1;  continue; }

    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      PE2 = NULL;
      PE5 = ActK1->Effect;
      for (j = 0; j < EffIdx[i]; j++) PE2=PE5,PE5=PE5->next;

      if (PE2 == NULL) ActK1->Effect = PE5->next;
      else PE2->next = PE5->next;

      FreeTokenList(PE5->Pred);  free(PE5);
    }

    if (PE3 == NULL) ActK->Effect = PE4;
    else PE3->next = PE4;

    PE1->next = Pd->CEffect;
    Pd->CEffect = PE1;
  }

  free(EffIdx);
}

void AddOneLeafOfPlanTree(ReadyTreeLeaf **RT, int Idx, PlanTreeLeaf *PT)
{
  PredKnowledge *Pd, *Pred;
  ReadyTreeLeaf *RT1, *RT2;
  ActKnowledge  *ActK, *ActK1, *ActK2;

  RT1 = (ReadyTreeLeaf *) calloc(1, sizeof(ReadyTreeLeaf));

  RT1->Ready = TRUE;
  RT1->TIndex = Idx;
  RT1->Index = PT->Index;

  Pred = PT->Pred;

  RT1->Pred = Pd = (PredKnowledge *) calloc(1, sizeof(PredKnowledge));
  Pd->Fact = Pred->Fact;
  Pd->Type = Pred->Type;
  Pd->Level = Pred->Level;
  Pd->Character = Pred->Character;
  Pd->Acts = Pred->Acts;
  Pd->Height = Pred->Height;
  Pd->Parent = Pred->Parent;
  Pd->PredNo = Pred->PredNo;
  Pd->NumEP = Pred->NumEP;
  Pd->Para = CopyTypedArray(NumParaOfPred(Pred->PredNo)+Pred->NumEP, Pred->Para);

  CopyListOfCEffect(Pd, Pred);

  ActK2 = NULL;
  for (ActK = Pred->Act; ActK != NULL; ActK = ActK->next) {
    if (!IsValid(Pred, ActK)) continue;

    ActK1 = CopyActKnowledge(ActK, Pd);

    if (ActK2 != NULL) InsertActKnowledge(AFTER, ActK2, ActK1);
    else { Pd->Act = ActK1;  Pd->NumAct++; }

    ActK2 = ActK1;
  }

  GetCommonEffectOfPred(Pd);

  RT2 = *RT;
  if (RT2 == NULL) *RT = RT1;
  else {
         while (RT2->next != NULL) RT2 = RT2->next;
         RT2->next = RT1;
  }
}

RelationOfLeaf *DeleteRelationOfLeaf(RelationOfLeaf *RL, int Level, int Index)
{
  RelationOfLeaf *RL1, *RL2, *RL3;

  RL1 = NULL;
  while (RL != NULL) {
    RL2 = RL->next;

    if (RL->PT1->Pred->Level==Level && RL->Idx1==Index) free(RL);
    else {
           if (RL1 == NULL) RL1 = RL;
           else RL3->next = RL;
           RL3 = RL;
    }

    RL = RL2;
  }

  return RL1;
}

void CheckLeavesOfPlanTree(PlanTreeLeaf *PT)
{
  RelationOfLeaf *RL, *RL1, *RL2;
  PlanTreeLeaf   *PT1, *PT2;
  int             Index, Level;

  PT2 = PT;
  Index = PT->Index;
  Level = PT->Pred->Level;

  RL = NULL;
  while (PT != NULL) {
    if (PT->Index!=Index || PT->Pred->Level!=Level) break;

    for (PT1 = PT->next; PT1 != NULL; PT1 = PT1->next)
      if (PT1->Pred->Level != Level) break;

    for (; PT1 != NULL; PT1 = PT1->next) {
      if (!PredObsPred(PT->Pred, PT1->Pred)) break;

      RL1 = (RelationOfLeaf *) calloc(1, sizeof(RelationOfLeaf));

      RL1->Idx1 = PT->Index;
      RL1->PT1 = PT;
      RL1->Idx2 = PT1->Index;
      RL1->PT2 = PT1;
      RL1->Obs = PredObsPred(PT1->Pred, PT->Pred);

      if (RL == NULL) RL = RL1;
      else RL2->next = RL1;

      RL2 = RL1;
    }

    if (PT1 != NULL) break;

    PT = PT->next;
  }

/*for (RL1 = RL; RL1 != NULL; RL1 = RL1->next)
    fprintf(Output, "%d-%p(%d) vs %d-%p(%d), Obs:%d\n",
                     RL1->PT1->Pred->Level, RL1->PT1, RL1->Idx1,
                     RL1->PT2->Pred->Level, RL1->PT2, RL1->Idx2,
                     RL1->Obs);*/

  for (RL1 = RL; RL1 != NULL; RL1 = RL1->next)
    if (!RL1->Obs) break;

  if (RL1 != NULL)
     while (PT2 != NULL) {
       if (PT2->Index!=Index || PT2->Pred->Level!=Level) break;

       PT2->Delete = TRUE;
       PT2 = PT2->next;
     }

  for (RL1 = RL; RL1 != NULL; RL1 = RL2) {
    RL2 = RL1->next;
    free(RL1);
  }
}

void HandleLeavesOfTarget(OneTarget *OT)
{
  PlanTreeLeaf *PT, *PT1, *PT2, *PT3, *PT4;
  int           k;

  k = NOFOUND;
  for (PT = OT->Leaf; PT != NULL; PT = PT->next)
    if (PT->Index == NOFOUND) {
       PT->Index = ++k;
       for (PT1 = PT->next; PT1 != NULL; PT1 = PT1->next)
         if (PT1->Index==NOFOUND && EqualTwoPredications(PT->Pred, PT1->Pred))
            PT1->Index = k;
    }

  OT->Level = NOFOUND;

  PT = OT->Leaf;
  if (PT == NULL) return;

  PT1 = PT->next;  PT->next = NULL;
  while (PT1 != NULL) {
    PT4 = PT1->next;

    k = PT1->Pred->Level;
    PT2 = NULL;
    for (PT3 = PT; PT3 != NULL; PT2=PT3,PT3=PT3->next)
      if (PT3->Pred->Level < k || PT3->Index > PT1->Index) break;

    if (PT2 == NULL) { PT1->next = PT;  PT = PT1; }
    else { PT1->next = PT2->next; PT2->next = PT1; }

    PT1 = PT4;
  }

  OT->Leaf = PT;  OT->Level = PT->Pred->Level;
}

ReadyTreeLeaf* GetReadyLeavesOfPlanTree3(PriorList *PL)
{
  ReadyTreeLeaf *PT;
  PlanTreeLeaf  *Pt1, *Pt2;
  OneTarget     *OT;
  PriorList     *PL1;
  int           Level, Index;

  OT = (OneTarget *) calloc(1, sizeof(OneTarget));

  PT = NULL;
  for ( ; PL != NULL; PL = PL1) {
    OT->Leaf = NULL;
    GetLeavesOfOneTarget(OT, PL->Pred);

    HandleLeavesOfTarget(OT);

    Index = NOFOUND;
    Level = OT->Level;
    for (Pt1 = OT->Leaf; Pt1 != NULL; Pt1 = Pt2) {
      if (Pt1->Pred->Level == Level && Index != Pt1->Index) {
         Index = Pt1->Index;
         AddOneLeafOfPlanTree(&PT, PL->Index, Pt1);
      }
      Pt2 = Pt1->next;
      free(Pt1);
    }

    PL1 = PL->next;
    free(PL);
  }

  free(OT);

  return GetReadyLeavesOfPlanTree(PT);
}

ReadyTreeLeaf* GetReadyLeavesOfPlanTree2(int *HT)
{
  PredKnowledge *Pd;
  ReadyTreeLeaf *PT;
  PlanTreeLeaf  *Pt2;
  OneTarget     *OT;
  int           i, Num, Index, Level;
  TypeOfPred    TypeOfPd;

  PT = NULL;
  for (i = 1; i <= HT[0]; i++) {
    OT = Target + HT[i];

    if (OT->Waiting) continue;

    Pt2 = OT->Leaf;
    while (Pt2 != NULL) {
      CheckLeavesOfPlanTree(Pt2);

      Index = Pt2->Index;
      Level = Pt2->Pred->Level;
      while (Pt2!=NULL && Pt2->Index==Index && Pt2->Pred->Level==Level)
        Pt2 = Pt2->next;
    }

    Num = OT->Level;
    for (Pt2 = OT->Leaf; Pt2 != NULL; Pt2 = Pt2->next)
      if (!Pt2->Delete) { Num = Pt2->Pred->Level;  break; }

    while (Pt2 != NULL) {
      Pd = Pt2->Pred;
      TypeOfPd = ClassOfPred(Pd->PredNo);
      if ((!Pt2->Delete && Pd->Level == Num) ||
          (Pd->Type == ATOM && TypeOfPd == ASCENDING) ||
          (Pd->Type == NOT && TypeOfPd == DESCENDING))
         AddOneLeafOfPlanTree(&PT, HT[i], Pt2);

      Pt2 = Pt2->next;
    }
  }

  return GetReadyLeavesOfPlanTree(PT);
}
